package hunterxhunter.greedisland.data;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.MessageDigest;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

/**
 *
 * @author Markus Schr&ouml;der
 */
public abstract class CipherSerializable {

    //crypto
    private SecretKeySpec key;
    private Cipher aes;
    
    public abstract String getPassphrase();
    public abstract void write(ObjectOutputStream oos) throws IOException;
    public abstract void read(ObjectInputStream ois) throws IOException, ClassNotFoundException;
    
    public CipherSerializable() {
        createKey();
    }
    
    public void save(File file) {
        
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            ObjectOutputStream oos = new ObjectOutputStream(baos);
            write(oos);
            oos.close();
        
            baos.close();
            
            aes.init(Cipher.ENCRYPT_MODE, key);
            byte[] ciphertext = aes.doFinal(baos.toByteArray());
            
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(ciphertext);
            fos.close();
            
        } catch (Exception ex) {
            Logger.getLogger(Ring.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    public void load(File file) {
        
        try {
            FileInputStream fis = new FileInputStream(file);
            byte[] fileBytes = new byte[(int)file.length()];
            fis.read(fileBytes);
            fis.close();
            
            aes.init(Cipher.DECRYPT_MODE, key);
            fileBytes = aes.doFinal(fileBytes);
            
            ByteArrayInputStream bais = new ByteArrayInputStream(fileBytes);
            ObjectInputStream ois = new ObjectInputStream(bais);
            read(ois);
            ois.close();
        
        } catch (Exception ex) {
            Logger.getLogger(Ring.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    private void createKey() {
        try {
            aes = Cipher.getInstance("AES/ECB/PKCS5Padding");
            String passphrase = getPassphrase();
            MessageDigest digest = MessageDigest.getInstance("SHA");
            digest.update(passphrase.getBytes());
            key = new SecretKeySpec(digest.digest(), 0, 16, "AES");
        } catch (Exception ex) {
            Logger.getLogger(Ring.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
}
